/*
 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2016 Semtech

Description: Handling of the node configuration protocol

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Miguel Luis, Gregory Cristian and Matthieu Verdy
*/
#include "sx126x-hal.h"
#include <wiringPi.h>

#include <unistd.h>
#include <assert.h>

#define BOARD_TCXO_WAKEUP_TIME    5 // no TCXO

#define RADIO_RESET_PIN							  3

#define RADIO_NSS_PIN                             23

#define RADIO_BUSY_PIN                            1

#define RADIO_DIO_1_PIN                           7


extern int  spi_sx;
#define LORA_SPI			spi_sx



/*!
 * \brief Used to block execution waiting for low state on radio busy pin.
 */
#define WaitOnBusy( )             while( digitalRead(RADIO_BUSY_PIN) == 1 );


/*!
 * \brief Used to block execution to give enough time to Busy to go up
 *        in order to respect Tsw, see datasheet ยง8.3.1
 */
#define WaitOnCounter( )          delay(1)

void HAL_delay(int ms)
{
    delay(ms);
}

void Reset( void )
{
    wiringPiSetup();

    pinMode( RADIO_RESET_PIN, OUTPUT );
    pinMode( RADIO_BUSY_PIN, INPUT );
    pinMode( RADIO_DIO_1_PIN, INPUT );
    pinMode( RADIO_NSS_PIN, OUTPUT );

    digitalWrite( RADIO_RESET_PIN, LOW );

	// Wait 20 ms
	delay( 20 );

	digitalWrite( RADIO_RESET_PIN, HIGH );

	// Wait 10 ms
	delay( 10 );
}

void Wakeup( void )
{
	uint8_t txData;

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

	txData = (uint8_t)RADIO_GET_STATUS;
	write( LORA_SPI, &txData, 1 );

	txData = (uint8_t)0;
	write ( LORA_SPI, &txData, 1 );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );

    // Wait for chip to be ready.
    WaitOnBusy( );
}

void WriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
{
	uint8_t txData;

#ifdef ADV_DEBUG
    printf("cmd: 0x%02x", command );
    for( uint8_t i = 0; i < size; i++ )
    {
        printf("-%02x", buffer[i] );
    }
    printf("\n\r");
#endif
    
    WaitOnBusy( );

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

	txData = (uint8_t)command;
	write( LORA_SPI, &txData, 1 );

	write( LORA_SPI, buffer, size );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );

    WaitOnCounter( );
}

void ReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
{
    uint8_t status = 0;
    uint8_t txData;

    WaitOnBusy( );

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

	txData = (uint8_t)command;
	write( LORA_SPI, &txData, 1 );

	write( LORA_SPI, &status, 1 );

    read( LORA_SPI, buffer, size );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );
}

void WriteRegister( uint16_t address, uint8_t *buffer, uint16_t size )
{
	uint8_t	txData[3];

    WaitOnBusy( );

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

	txData[0] = (uint8_t)RADIO_WRITE_REGISTER;
	txData[1] = (uint8_t)(( address & 0xFF00 ) >> 8);
	txData[2] = (uint8_t)(address & 0x00FF );
	write( LORA_SPI, txData, 3 );

	write( LORA_SPI, buffer, size );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );
}

void WriteReg( uint16_t address, uint8_t value )
{
    WriteRegister( address, &value, 1 );
}

void ReadRegister( uint16_t address, uint8_t *buffer, uint16_t size )
{
	uint8_t	txData[4];

    WaitOnBusy( );

    //NSS = 0;
     digitalWrite( RADIO_NSS_PIN, LOW );

 	txData[0] = (uint8_t)RADIO_READ_REGISTER;
 	txData[1] = (uint8_t)(( address & 0xFF00) >> 8 );
 	txData[2] = (uint8_t)(address & 0x00FF);
 	txData[0] = (uint8_t)0;
 	 write( LORA_SPI, txData, 4 );

 	read( LORA_SPI, buffer, size );

     //NSS = 1;
     digitalWrite( RADIO_NSS_PIN, HIGH );
}

uint8_t ReadReg( uint16_t address )
{
    uint8_t data;

    ReadRegister( address, &data, 1 );
    return data;
}

void WriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
{
	uint8_t	txData[2];

    WaitOnBusy( );

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

    txData[0] = RADIO_WRITE_BUFFER;
    txData[1] = offset;
    write( LORA_SPI, txData, 2 );

    write( LORA_SPI, buffer, size );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );
}

void ReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
{
	uint8_t	txData[3];

    WaitOnBusy( );

    //NSS = 0;
    digitalWrite( RADIO_NSS_PIN, LOW );

    txData[0] = RADIO_READ_BUFFER;
    txData[1] = offset;
    txData[2] = 0;
    write( LORA_SPI, txData, 3 );

    read( LORA_SPI, buffer, size );

    //NSS = 1;
    digitalWrite( RADIO_NSS_PIN, HIGH );
}

uint8_t GetDioStatus( void )
{
	// TODO:
	return 0;
//    return ( *DIO3 << 3 ) | ( *DIO2 << 2 ) | ( *DIO1 << 1 ) | ( BUSY << 0 );
}

uint8_t GetDeviceType( void )
{

	return( SX1262 );
}

bool IRQCheck()
{
    return ( digitalRead(RADIO_DIO_1_PIN) == 1 );
}